home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / TARGA.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-15  |  30.6 KB  |  1,371 lines

  1. /****************************************************************************
  2. *                targa.c
  3. *
  4. *  This module contains the code to read and write the Targa output file
  5. *  format.
  6. *
  7. *  from Persistence of Vision(tm) Ray Tracer
  8. *  Copyright 1996 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  NOTICE: This source code file is provided so that users may experiment
  11. *  with enhancements to POV-Ray and to port the software to platforms other
  12. *  than those supported by the POV-Ray Team.  There are strict rules under
  13. *  which you are permitted to use this file.  The rules are in the file
  14. *  named POVLEGAL.DOC which should be distributed with this file. If
  15. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  17. *  Forum.  The latest version of POV-Ray may be found there as well.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24.  
  25. /****************************************************************************
  26. *
  27. *  Explanation:
  28. *
  29. *    -
  30. *
  31. *  ---
  32. *
  33. *  May 1994 : Support for 24-bit RLE Targa output files added: John Baily
  34. *             and David Payne.
  35. *
  36. *  Jul 1994 : Resume trace support and minor algorithm fix (one more still
  37. *             needed, see comments in Write_Targa_Line); resume will force
  38. *             Targa format to match the original trace format -- the T or C
  39. *             format flag is adjusted as necessary: Charles Marslett,
  40. *
  41. *  Jun 1995 : Added support for 32-bit Targa input and output files.
  42. *             The alpha channel has a value of 0 for 100% transparency
  43. *             and a value of 255 for 0% transparency. [DB]
  44. *
  45. *****************************************************************************/
  46.  
  47. #include "frame.h"
  48. #include "povproto.h"
  49. #include "povray.h"
  50. #include "targa.h"
  51.  
  52.  
  53.  
  54. /*****************************************************************************
  55. * Local preprocessor defines
  56. ******************************************************************************/
  57.  
  58. #define boolean  int
  59.  
  60.  
  61.  
  62. /*****************************************************************************
  63. * Local typedefs
  64. ******************************************************************************/
  65.  
  66. typedef struct pix
  67. {
  68.   DBL blue, green, red, transm;
  69. } pix;
  70.  
  71.  
  72.  
  73. /*****************************************************************************
  74. * Local variables
  75. ******************************************************************************/
  76.  
  77. static int Targa_Line_Number;
  78. static unsigned char idbuf[256];
  79.  
  80.  
  81.  
  82. /*****************************************************************************
  83. * Static functions
  84. ******************************************************************************/
  85.  
  86. static void convert_targa_color PARAMS((IMAGE_COLOUR *, unsigned, unsigned char *));
  87. static int Open_Targa_File PARAMS((FILE_HANDLE *handle, char *name, int *width, 
  88.   int *height, int buffer_size, int mode));
  89. static void Write_Targa_Line PARAMS((FILE_HANDLE *handle, COLOUR *line_data, int line_number));
  90. static int Read_Targa_Line PARAMS((FILE_HANDLE *handle, COLOUR *line_data, int *line_number));
  91. static void Close_Targa_File PARAMS((FILE_HANDLE *handle));
  92. static void Write_Targa_Pixel PARAMS((FILE_HANDLE *handle, DBL b, DBL g, DBL r, DBL f));
  93.  
  94.  
  95.  
  96. /*****************************************************************************
  97. *
  98. * FUNCTION
  99. *
  100. *   Get_Targa_File_Handle
  101. *
  102. * INPUT
  103. *   
  104. * OUTPUT
  105. *   
  106. * RETURNS
  107. *   
  108. * AUTHOR
  109. *
  110. *   POV-Ray Team
  111. *   
  112. * DESCRIPTION
  113. *
  114. *   -
  115. *
  116. * CHANGES
  117. *
  118. *   -
  119. *
  120. ******************************************************************************/
  121.  
  122. FILE_HANDLE *Get_Targa_File_Handle()
  123. {
  124.   FILE_HANDLE *handle;
  125.  
  126.   handle = (FILE_HANDLE *)POV_MALLOC(sizeof(FILE_HANDLE), "TGA file handle");
  127.  
  128.   handle->Open_File_p         = Open_Targa_File;
  129.   handle->Write_Line_p        = Write_Targa_Line;
  130.   handle->Read_Line_p         = Read_Targa_Line;
  131.   handle->Read_Image_p        = Read_Targa_Image;
  132.   handle->Close_File_p        = Close_Targa_File;
  133.  
  134.   handle->file = NULL;
  135.   handle->buffer = NULL;
  136.   handle->buffer_size = 0;
  137.  
  138.   return(handle);
  139. }
  140.  
  141.  
  142. /*****************************************************************************
  143. *
  144. * FUNCTION
  145. *
  146. *   Open_Targa_File
  147. *
  148. * INPUT
  149. *   
  150. * OUTPUT
  151. *   
  152. * RETURNS
  153. *   
  154. * AUTHOR
  155. *
  156. *   POV-Ray Team
  157. *   
  158. * DESCRIPTION
  159. *
  160. *   -
  161. *
  162. * CHANGES
  163. *
  164. *   Jun 1995 : Added code for 32 bit Targa files. [DB]
  165. *
  166. *   Sept 1995: Modified header output for Targa files. [AED]
  167. *
  168. ******************************************************************************/
  169.  
  170. static int Open_Targa_File (handle, name, width, height, buffer_size, mode)
  171. FILE_HANDLE *handle;
  172. char *name;
  173. int *width;
  174. int *height;
  175. int buffer_size;
  176. int mode;
  177. {
  178.   unsigned char tgaheader[18];
  179.  
  180.   handle->mode = mode;
  181.   handle->filename = name;
  182.  
  183.   Targa_Line_Number = 0;
  184.  
  185.   switch (mode)
  186.   {
  187.     case READ_MODE:
  188.  
  189.       if ((handle->file = fopen(name, READ_FILE_STRING)) == NULL)
  190.       {
  191.         return(0);
  192.       }
  193.  
  194.       if (buffer_size != 0)
  195.       {
  196.         handle->buffer = POV_MALLOC((size_t)buffer_size, "TGA file buffer");
  197.         setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
  198.       }
  199.  
  200.       /* Read targa header information. */
  201.  
  202.       if (fread(tgaheader, 18, 1, handle->file) != 1)
  203.       {
  204.         return(0);
  205.       }
  206.  
  207.       /* Decipher the header information */
  208.  
  209.       switch (tgaheader[2])
  210.       {
  211.         case 2  : opts.OutputFormat = 'T'; break;
  212.         case 10 : opts.OutputFormat = 'C'; break;
  213.         default : return(0);
  214.       }
  215.  
  216.       switch (tgaheader[16])
  217.       {
  218.         case 24 : break;
  219.         case 32 : opts.Options |= OUTPUT_ALPHA; break;
  220.         default : return(0);
  221.       }
  222.  
  223.       /* First_Column set to x offset.  Bytes 8, 9 */
  224.       opts.First_Column = tgaheader[8] + (tgaheader[9] << 8);
  225.  
  226.       /* First line set to y offset.  Bytes 10, 11 */
  227.       opts.First_Line = Targa_Line_Number = tgaheader[10] + (tgaheader[11]<<8);
  228.  
  229.       handle->width  = *width  = tgaheader[12] + (tgaheader[13] << 8);
  230.       handle->height = *height = tgaheader[14] + (tgaheader[15] << 8);
  231.  
  232.       handle->buffer_size = buffer_size;
  233.   
  234.       break;
  235.  
  236.     case WRITE_MODE:
  237.  
  238.       if (!strcmp(name,"-"))
  239.       {
  240.         buffer_size = 0;
  241.         handle->file = stdout;
  242.       }
  243.       else if ((handle->file = fopen (name, WRITE_FILE_STRING)) == NULL)
  244.       {
  245.         return(0);
  246.       }
  247.  
  248.       if (buffer_size != 0)
  249.       {
  250.         handle->buffer = POV_MALLOC((size_t)buffer_size, "TGA file buffer");
  251.         setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
  252.       }
  253.  
  254.       /* Output TGA file header info */
  255.       putc(0, handle->file);  /* Byte 0 - Length of Image ID field */
  256.  
  257.       putc(0, handle->file);  /* Byte 1 - Color map type (0 is no color map) */
  258.  
  259.       switch(opts.OutputFormat)  /* Byte 2 - TGA file type */
  260.       {
  261.         case 't': /* Uncompressed True-Color Image */
  262.         case 'T': putc(2, handle->file); break;
  263.  
  264.         case 'c': /* Run-length compressed True-Color Image */
  265.         case 'C': putc(10, handle->file); break;
  266.       }
  267.  
  268.       putc(0, handle->file);  /* Byte 3 - Index of first color map entry LSB */
  269.       putc(0, handle->file);  /* Byte 4 - Index of first color map entry MSB */
  270.  
  271.       putc(0, handle->file);  /* Byte 5 - Color map length LSB */
  272.       putc(0, handle->file);  /* Byte 6 - Color map legth MSB */
  273.  
  274.       putc(0, handle->file);  /* Byte 7 - Color map size */
  275.  
  276.       /* x origin set to "First_Column"  Bytes 8, 9 */
  277.  
  278.       putc(opts.First_Column % 256, handle->file);
  279.       putc(opts.First_Column / 256, handle->file);
  280.  
  281.       /* y origin set to "First_Line"    Bytes 10, 11 */
  282.  
  283.       putc(opts.First_Line % 256, handle->file);
  284.       putc(opts.First_Line / 256, handle->file);
  285.  
  286.       /* write width and height  Bytes 12 - 15 */
  287.  
  288.       putc(*width % 256, handle->file);
  289.       putc(*width / 256, handle->file);
  290.       putc(*height % 256, handle->file);
  291.       putc(*height / 256, handle->file);
  292.  
  293.       /* We write 24 or 32 bits/pixel (16 million colors and alpha channel)
  294.        * and also store the orientation and Alpha channel depth.  Bytes 16, 17.
  295.        */
  296.       if (opts.Options & OUTPUT_ALPHA)
  297.       {
  298.         putc(32, handle->file);    /* 32 bits/pixel (BGRA) */
  299.         putc(0x28, handle->file);  /* Data starts at top left, 8 bits Alpha */
  300.       }
  301.       else
  302.       {
  303.         putc(24, handle->file);    /* 24 bits/pixel (BGR) */
  304.         putc(0x20, handle->file);  /* Data starts at top left, 0 bits Alpha */
  305.       }
  306.  
  307.       /* TGA file Image ID field data would go here (up to 255 chars) */
  308.  
  309.       handle->width = *width;
  310.       handle->height = *height;
  311.  
  312.       handle->buffer_size = buffer_size;
  313.  
  314.       break;
  315.  
  316.     case APPEND_MODE:
  317.  
  318.       if (!strcmp(name,"-"))
  319.       {
  320.         buffer_size = 0;
  321.         handle->file = stdout;
  322.       }
  323.       else if ((handle->file = fopen (name, APPEND_FILE_STRING)) == NULL)
  324.       {
  325.         return(0);
  326.       }
  327.  
  328.       if (buffer_size != 0)
  329.       {
  330.         handle->buffer = POV_MALLOC((size_t)buffer_size, "TGA file buffer");
  331.         setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
  332.       }
  333.  
  334.       break;
  335.   }
  336.  
  337.   return(1);
  338. }
  339.  
  340.  
  341.  
  342. /*****************************************************************************
  343. *
  344. * FUNCTION
  345. *
  346. *   Write_Targa_Pixel
  347. *
  348. * INPUT
  349. *
  350. *   handle     - Current file handel
  351. *   r, g, b, f - Color values to write
  352. *   
  353. * OUTPUT
  354. *   
  355. * RETURNS
  356. *   
  357. * AUTHOR
  358. *
  359. *   Dan Farmer
  360. *   
  361. * DESCRIPTION   :
  362. *
  363. *   Moves redundant code to a single function.  Adding 16 bit grayscale
  364. *   conditional code to each occurance of writing a pixel was getting a bit
  365. *   too wordy.
  366. *
  367. * CHANGES
  368. *
  369. *   Jun 1995 : Added code for 32 bit Targa files. [DB]
  370. *
  371. *   Sept 1995: Modified handling of Alpha channel to use only opts.Options
  372. *   Sept 1995: Modified handling of grayscale to use only opts.Options
  373. *
  374. ******************************************************************************/
  375.  
  376. static void Write_Targa_Pixel (handle, b, g, r, f)
  377. FILE_HANDLE *handle;
  378. DBL r, g, b, f;
  379. {
  380.   unsigned int gray;
  381.  
  382.   if (opts.Options & HF_GRAY_16)
  383.   {
  384.     /* Ouput heightfield in POV red/green format */
  385.     gray = ((0.30 * r) + (0.59 * g) + (0.11 * b)) * 65535;
  386.  
  387.     if ((putc(0 , handle->file) == EOF) ||
  388.         (putc(gray & 0xFF, handle->file) == EOF) ||
  389.         (putc((gray >> 8) & 0xFF, handle->file) == EOF))
  390.     {
  391.       Error("Error writing TGA output data to %s.\n",handle->filename);
  392.     }
  393.   }
  394.   else
  395.   {
  396.     /* Normal 24/32 bit pixel coloring */
  397.  
  398.     if ((putc((int) floor(b * 255.0), handle->file) == EOF) ||
  399.         (putc((int) floor(g * 255.0), handle->file) == EOF) ||
  400.         (putc((int) floor(r * 255.0), handle->file) == EOF))
  401.     {
  402.       Error("Error writing TGA output data to %s.\n",handle->filename);
  403.     }
  404.  
  405.     if (opts.Options & OUTPUT_ALPHA)
  406.     {
  407.       if (putc((int) floor((1.0 - f) * 255.0), handle->file) == EOF)
  408.       {
  409.         Error("Error writing TGA output data to %s.\n",handle->filename);
  410.       }
  411.     }
  412.   }
  413. }
  414.  
  415.  
  416. /*****************************************************************************
  417. *
  418. * FUNCTION
  419. *
  420. *   Write_Targa_Line
  421. *
  422. * INPUT
  423. *   
  424. * OUTPUT
  425. *   
  426. * RETURNS
  427. *   
  428. * AUTHOR
  429. *
  430. *   POV-Ray Team
  431. *   
  432. * DESCRIPTION
  433. *
  434. *   -
  435. *
  436. * CHANGES
  437. *
  438. *   Jun 1995 : Added code for 32 bit Targa files. [DB]
  439. *
  440. ******************************************************************************/
  441.  
  442. static void Write_Targa_Line (handle, line_data, line_number)
  443. FILE_HANDLE *handle;
  444. COLOUR *line_data;
  445. int line_number;
  446. {
  447.   register int x;
  448.   int ptype, cnt, llen, startx;
  449.   boolean writenow;
  450.   pix curpix, nexpix;
  451.  
  452.   switch (opts.OutputFormat)
  453.   {
  454.     case 't':
  455.     case 'T':
  456.  
  457.       for (x = 0; x < handle->width; x++)
  458.       {
  459.         Write_Targa_Pixel (handle, line_data[x][BLUE], line_data[x][GREEN], line_data[x][RED], line_data[x][TRANSM]);
  460.       }
  461.  
  462.       break;
  463.  
  464.     case 'c':
  465.     case 'C':
  466.  
  467.       llen = handle->width;
  468.  
  469.       startx = 0;
  470.  
  471.       cnt = 1;
  472.  
  473.       curpix.blue   = line_data[startx][BLUE];
  474.       curpix.green  = line_data[startx][GREEN];
  475.       curpix.red    = line_data[startx][RED];
  476.       curpix.transm = line_data[startx][TRANSM];
  477.  
  478.       ptype = 0;
  479.  
  480.       writenow = FALSE;
  481.  
  482.       for (;;)
  483.       {
  484.         nexpix.blue   = line_data[startx+cnt][BLUE];
  485.         nexpix.green  = line_data[startx+cnt][GREEN];
  486.         nexpix.red    = line_data[startx+cnt][RED];
  487.         nexpix.transm = line_data[startx+cnt][TRANSM];
  488.  
  489.         if ((nexpix.red == curpix.red) && (nexpix.blue == curpix.blue) &&
  490.             (nexpix.green == curpix.green) && (nexpix.transm == curpix.transm))
  491.         {
  492.           if (ptype == 0)
  493.           {
  494.             cnt++;
  495.  
  496.             if ((cnt >= 128) || ((startx + cnt) >= llen))
  497.             {
  498.               writenow = TRUE;
  499.             }
  500.           }
  501.           else
  502.           {
  503.             cnt--;
  504.  
  505.             writenow = TRUE;
  506.           }
  507.         }
  508.         else
  509.         {
  510.           if ((ptype == 1) || (cnt <= 1))
  511.           {
  512.             ptype = 1;
  513.  
  514.             curpix = nexpix;
  515.  
  516.             cnt++;
  517.  
  518.             if ((cnt >= 128) || ((startx + cnt) >= llen))
  519.             {
  520.               writenow = TRUE;
  521.             }
  522.           }
  523.           else
  524.           {
  525.             writenow = TRUE;
  526.           }
  527.         }
  528.  
  529.         if (writenow)
  530.         {
  531.           /* This test SHOULD be unnecessary!  However, it isn't!  [CWM] */
  532.  
  533.           if (startx + cnt > llen)
  534.           {
  535.             cnt = llen - startx;
  536.           }
  537.  
  538.           if (ptype == 0)
  539.           {
  540.             putc((int) ((cnt - 1) | 0x80), handle->file);
  541.  
  542.             Write_Targa_Pixel (handle, curpix.blue, curpix.green, curpix.red, curpix.transm);
  543.  
  544.             curpix = nexpix;
  545.           }
  546.           else
  547.           {
  548.             putc((int) cnt - 1, handle->file);
  549.  
  550.             for (x = 0; x < cnt; x++)
  551.             {
  552.                Write_Targa_Pixel (handle,
  553.                  line_data[startx+x][BLUE], line_data[startx+x][GREEN],
  554.                  line_data[startx+x][RED], line_data[startx+x][TRANSM]);
  555.             }
  556.           }
  557.           startx = startx + cnt;
  558.  
  559.           writenow = FALSE;
  560.  
  561.           ptype = 0;
  562.  
  563.           cnt = 1;
  564.  
  565.           if (startx >= llen)
  566.           {
  567.              break; /* Exit while */
  568.           }
  569.         }
  570.       }
  571.  
  572.       break; /* End of case */
  573.   }
  574.  
  575.   if (handle->buffer_size == 0)
  576.   {
  577.     /* Close and reopen file (if not stdout) for integrity in case we crash */
  578.  
  579.     fflush(handle->file);
  580.  
  581.     if (strcmp(handle->filename, "-"))
  582.     {
  583.       handle->file = freopen(handle->filename, APPEND_FILE_STRING, handle->file);
  584.     }
  585.   }
  586. }
  587.  
  588.  
  589.  
  590. /*****************************************************************************
  591. *
  592. * FUNCTION
  593. *
  594. *   Read_Targa_Line
  595. *
  596. * INPUT
  597. *   
  598. * OUTPUT
  599. *   
  600. * RETURNS
  601. *   
  602. * AUTHOR
  603. *
  604. *   POV-Ray Team
  605. *   
  606. * DESCRIPTION
  607. *
  608. *   -
  609. *
  610. * CHANGES
  611. *
  612. *   Jun 1995 : Added code for 32 bit Targa files. [DB]
  613. *
  614. ******************************************************************************/
  615.  
  616. static int Read_Targa_Line (handle, line_data, line_number)
  617. FILE_HANDLE *handle;
  618. COLOUR *line_data;
  619. int *line_number;
  620. {
  621.   int x, data, cnt;
  622.   DBL rdata, gdata, bdata, fdata;
  623.  
  624.   switch (opts.OutputFormat)
  625.   {
  626.     case 't':
  627.     case 'T':
  628.  
  629.       for (x = 0; x < handle->width; x++)
  630.       {
  631.         /* Read the BLUE data byte.  If EOF is reached on the first
  632.          * character read, then this line hasn't been rendered yet.
  633.          * Return 0.  If an EOF occurs somewhere within the line, this
  634.          * is an error - return -1.
  635.          */
  636.  
  637.         if ((data = getc(handle->file)) == EOF)
  638.         {
  639.           if (x == 0)
  640.           {
  641.             return(0);
  642.           }
  643.           else
  644.           {
  645.             return(-1);
  646.           }
  647.         }
  648.  
  649.         line_data[x][BLUE] = (DBL) data / 255.0;
  650.  
  651.         /* Read the GREEN data byte. */
  652.  
  653.         if ((data = getc(handle->file)) == EOF)
  654.         {
  655.           return(-1);
  656.         }
  657.  
  658.         line_data[x][GREEN] = (DBL) data / 255.0;
  659.  
  660.         /* Read the RED data byte. */
  661.  
  662.         if ((data = getc(handle->file)) == EOF)
  663.         {
  664.           return(-1);
  665.         }
  666.  
  667.         line_data[x][RED] = (DBL) data / 255.0;
  668.  
  669.         /* Read alpha channel. */
  670.  
  671.         if (opts.Options & OUTPUT_ALPHA)
  672.         {
  673.           if ((data = getc(handle->file)) == EOF)
  674.           {
  675.             return(-1);
  676.           }
  677.  
  678.           line_data[x][TRANSM] = 1.0 - (DBL)data / 255.0;
  679.         }
  680.         else
  681.         {
  682.           line_data[x][TRANSM] = 0.0;
  683.         }
  684.       }
  685.  
  686.       break;
  687.  
  688.     case 'c':
  689.     case 'C':
  690.  
  691.       cnt = 0;
  692.  
  693.       do
  694.       {
  695.         if ((data = getc(handle->file)) == EOF)
  696.         {
  697.           if (cnt == 0)
  698.           {
  699.             return(0);
  700.           }
  701.           else
  702.           {
  703.             return(-1);
  704.           }
  705.         }
  706.  
  707.         if (data & 0x80)
  708.         {
  709.           x = data & 0x7F;
  710.  
  711.           if ((data = getc(handle->file)) == EOF)
  712.           {
  713.             return(-1);
  714.           }
  715.  
  716.           bdata = (DBL) data / 255.0;
  717.  
  718.           if ((data = getc(handle->file)) == EOF)
  719.           {
  720.             return(-1);
  721.           }
  722.  
  723.           gdata = (DBL) data / 255.0;
  724.  
  725.           if ((data = getc(handle->file)) == EOF)
  726.           {
  727.             return(-1);
  728.           }
  729.  
  730.           rdata = (DBL) data / 255.0;
  731.  
  732.           /* Read alpha channel if any. */
  733.  
  734.           if (opts.Options & OUTPUT_ALPHA)
  735.           {
  736.             if ((data = getc(handle->file)) == EOF)
  737.             {
  738.               return(-1);
  739.             }
  740.  
  741.             fdata = 1.0 - (DBL)data / 255.0;
  742.           }
  743.           else
  744.           {
  745.             fdata = 0.0;
  746.           }
  747.  
  748.           do
  749.           {
  750.             line_data[cnt][BLUE]   = bdata;
  751.             line_data[cnt][GREEN]  = gdata;
  752.             line_data[cnt][RED]    = rdata;
  753.             line_data[cnt][TRANSM] = fdata;
  754.  
  755.             cnt++;
  756.           }
  757.           while (--x != -1);
  758.         }
  759.         else
  760.         {
  761.           x = data & 0x7F;
  762.  
  763.           do
  764.           {
  765.             if ((data = getc(handle->file)) == EOF)
  766.             {
  767.               return(-1);
  768.             }
  769.  
  770.             bdata = (DBL) data / 255.0;
  771.  
  772.             if ((data = getc(handle->file)) == EOF)
  773.             {
  774.               return(-1);
  775.             }
  776.  
  777.             gdata = (DBL) data / 255.0;
  778.  
  779.             if ((data = getc(handle->file)) == EOF)
  780.             {
  781.               return(-1);
  782.             }
  783.  
  784.             rdata = (DBL) data / 255.0;
  785.  
  786.             /* Read alpha channel if any. */
  787.  
  788.             if (opts.Options & OUTPUT_ALPHA)
  789.             {
  790.               if ((data = getc(handle->file)) == EOF)
  791.               {
  792.                 return(-1);
  793.               }
  794.  
  795.               fdata = 1.0 - (DBL)data / 255.0;
  796.             }
  797.             else
  798.             {
  799.               fdata = 0.0;
  800.             }
  801.  
  802.             line_data[cnt][BLUE]   = bdata;
  803.             line_data[cnt][GREEN]  = gdata;
  804.             line_data[cnt][RED]    = rdata;
  805.             line_data[cnt][TRANSM] = fdata;
  806.  
  807.             cnt++;
  808.           }
  809.           while (--x != -1);
  810.         }
  811.       }
  812.       while (cnt < handle->width);
  813.  
  814.       if (cnt != handle->width)
  815.       {
  816.         return(-1);
  817.       }
  818.  
  819.       break;
  820.   }
  821.  
  822.   *line_number = Targa_Line_Number++;
  823.  
  824.   return(1);
  825. }
  826.  
  827.  
  828.  
  829. /*****************************************************************************
  830. *
  831. * FUNCTION
  832. *
  833. *   Close_Targa_File
  834. *
  835. * INPUT
  836. *   
  837. * OUTPUT
  838. *   
  839. * RETURNS
  840. *   
  841. * AUTHOR
  842. *
  843. *   POV-Ray Team
  844. *   
  845. * DESCRIPTION
  846. *
  847. *   -
  848. *
  849. * CHANGES
  850. *
  851. *   -
  852. *
  853. ******************************************************************************/
  854.  
  855. static void Close_Targa_File (handle)
  856. FILE_HANDLE *handle;
  857. {
  858.   if (handle->file)
  859.   {
  860.     fflush(handle->file);
  861.     fclose (handle->file);
  862.   }
  863.  
  864.   if (handle->buffer != NULL)
  865.   {
  866.     POV_FREE (handle->buffer);
  867.   }
  868.  
  869.   handle->file = NULL;
  870.   handle->buffer = NULL;
  871. }
  872.  
  873.  
  874.  
  875. /*****************************************************************************
  876. *
  877. * FUNCTION
  878. *
  879. *   convert_targa_color
  880. *
  881. * INPUT
  882. *   
  883. * OUTPUT
  884. *   
  885. * RETURNS
  886. *   
  887. * AUTHOR
  888. *
  889. *   POV-Ray Team
  890. *   
  891. * DESCRIPTION
  892. *
  893. *   -
  894. *
  895. * CHANGES
  896. *
  897. *   -
  898. *
  899. ******************************************************************************/
  900.  
  901. static void convert_targa_color(tcolor, pixelsize, bytes)
  902. IMAGE_COLOUR *tcolor;
  903. unsigned pixelsize;
  904. unsigned char *bytes;
  905. {
  906.   switch (pixelsize)
  907.   {
  908.     case 1:
  909.  
  910.       tcolor->Red    = bytes[0];
  911.       tcolor->Green  = bytes[0];
  912.       tcolor->Blue   = bytes[0];
  913.       tcolor->Filter = 0;
  914.       tcolor->Transmit = 0;
  915.  
  916.       break;
  917.  
  918.     case 2:
  919.  
  920.       tcolor->Red    = ((bytes[1] & 0x7c) << 1);
  921.       tcolor->Green  = (((bytes[1] & 0x03) << 3) | ((bytes[0] & 0xe0) >> 5)) << 3;
  922.       tcolor->Blue   = (bytes[0] & 0x1f) << 3;
  923.       tcolor->Filter = 0;
  924.       tcolor->Transmit = 255 - (bytes[1] & 0x80 ? 255 : 0);
  925.  
  926.       break;
  927.  
  928.     case 3:
  929.  
  930.       tcolor->Red    = bytes[2];
  931.       tcolor->Green  = bytes[1];
  932.       tcolor->Blue   = bytes[0];
  933.       tcolor->Filter = 0;
  934.       tcolor->Transmit = 0;
  935.  
  936.       break;
  937.  
  938.     case 4:
  939.  
  940.       tcolor->Red    = bytes[2];
  941.       tcolor->Green  = bytes[1];
  942.       tcolor->Blue   = bytes[0];
  943.       tcolor->Filter = 0;
  944.       tcolor->Transmit = 255 - bytes[3];
  945.  
  946.       break;
  947.  
  948.     default:
  949.  
  950.       Error("Bad pixelsize in TGA color.\n");
  951.   }
  952. }
  953.  
  954.  
  955.  
  956. /*****************************************************************************
  957. *
  958. * FUNCTION
  959. *
  960. *   Read_Targa_Image
  961. *
  962. * INPUT
  963. *   
  964. * OUTPUT
  965. *   
  966. * RETURNS
  967. *   
  968. * AUTHOR
  969. *
  970. *   POV-Ray Team
  971. *   
  972. * DESCRIPTION
  973. *
  974. *   Reads a Targa image into an RGB image buffer.  Handles 8, 16, 24, 32 bit
  975. *   formats.  Raw or color mapped. Simple raster and RLE compressed pixel
  976. *   encoding. Right side up or upside down orientations.
  977. *
  978. * CHANGES
  979. *
  980. *   Jun 1995 : Added code for 32 bit Targa files. [DB]
  981. *
  982. ******************************************************************************/
  983.  
  984. void Read_Targa_Image(Image, name)
  985. IMAGE *Image;
  986. char *name;
  987. {
  988.   int h;
  989.   int temp;
  990.   unsigned i, j, k; 
  991. /*  unsigned long i, j, k; */
  992.   unsigned char cflag = 0, *map_line = NULL, bytes[4], tgaheader[18];
  993.   unsigned ftype, idlen, cmlen, cmsiz, psize, orien;
  994.   unsigned width, height;
  995.   FILE *filep;
  996.   IMAGE_LINE *line_data = NULL;
  997.   IMAGE_COLOUR *cmap, pixel;
  998.  
  999.   /* Start by trying to open the file */
  1000.  
  1001.   if ((filep = Locate_File(name, READ_FILE_STRING,".tga",".TGA",TRUE)) == NULL)
  1002.   {
  1003.     Error ("Error opening TGA image.\n");
  1004.   }
  1005.  
  1006.   if (fread(tgaheader, 18, 1, filep) != 1)
  1007.   {
  1008.     Error ("Error reading header of TGA image.\n");
  1009.   }
  1010.  
  1011.   /* Decipher the header information */
  1012.  
  1013.   idlen  = tgaheader[ 0];
  1014.   ftype  = tgaheader[ 2];
  1015.   cmlen  = tgaheader[ 5] + (tgaheader[ 6] << 8);
  1016.   cmsiz  = tgaheader[ 7] / 8;
  1017.   width  = tgaheader[12] + (tgaheader[13] << 8);
  1018.   height = tgaheader[14] + (tgaheader[15] << 8);
  1019.   psize  = tgaheader[16] / 8;
  1020.   orien  = tgaheader[17] & 0x20; /* Right side up ? */
  1021.  
  1022.   Image->iwidth  = width;
  1023.   Image->iheight = height;
  1024.   Image->width   = (DBL)width;
  1025.   Image->height  = (DBL)height;
  1026.   Image->Colour_Map_Size = cmlen;
  1027.   Image->Colour_Map = NULL;
  1028.  
  1029.   /* Determine if this is a supported Targa type */
  1030.  
  1031.   if (ftype == 9 || ftype == 10 || ftype == 11)
  1032.   {
  1033.     cflag = 1;
  1034.   }
  1035.   else
  1036.   {
  1037.     if (ftype == 1 || ftype == 2 || ftype == 3)
  1038.     {
  1039.       cflag = 0;
  1040.     }
  1041.     else
  1042.     {
  1043.       Error("Unsupported file type %d in TGA image.\n", ftype);
  1044.     }
  1045.   }
  1046.  
  1047.   /* Skip over the picture ID information */
  1048.  
  1049.   if (idlen > 0 && fread(idbuf, idlen, 1, filep) != 1)
  1050.   {
  1051.     Error ("Error reading header from TGA image.\n");
  1052.   }
  1053.  
  1054.   /* Read in the the color map (if any) */
  1055.  
  1056.   if (cmlen > 0)
  1057.   {
  1058.     if (psize != 1)
  1059.     {
  1060.       Error("Unsupported color map bit depth (%d bpp) in TGA image.\n",
  1061.             psize * 8);
  1062.     }
  1063.  
  1064.     cmap = (IMAGE_COLOUR *)POV_MALLOC(cmlen * sizeof(IMAGE_COLOUR), "TGA color map");
  1065.  
  1066.     for (i = 0; i < cmlen; i++)
  1067.     {
  1068.       for (j = 0; j < cmsiz; j++)
  1069.       {
  1070.         if ((temp = fgetc(filep)) == EOF)
  1071.         {
  1072.           Error("Error reading color map from TGA image.\n");
  1073.         }
  1074.         else
  1075.         {
  1076.           bytes[j] = (unsigned char)temp;
  1077.         }
  1078.       }
  1079.  
  1080.       convert_targa_color(&cmap[i], cmsiz, bytes);
  1081.     }
  1082.  
  1083.     Image->Colour_Map = cmap;
  1084.   }
  1085.   else
  1086.   {
  1087.     Image->Colour_Map = NULL;
  1088.   }
  1089.  
  1090.   /* Allocate the buffer for the image */
  1091.  
  1092.   if (cmlen > 0)
  1093.   {
  1094.     Image->data.map_lines = (unsigned char **)POV_MALLOC(height * sizeof(unsigned char *), "TGA image");
  1095.   }
  1096.   else
  1097.   {
  1098.     Image->data.rgb_lines = (IMAGE_LINE *)POV_MALLOC(height * sizeof(IMAGE_LINE), "TGA image");
  1099.   }
  1100.  
  1101.   for (i = 0; i < height; i++)
  1102.   {
  1103.     k = width * sizeof(unsigned char);
  1104.  
  1105.     if (cmlen > 0)
  1106.     {
  1107.       map_line = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  1108.  
  1109.       Image->data.map_lines[i] = map_line;
  1110.     }
  1111.     else
  1112.     {
  1113.       line_data = &Image->data.rgb_lines[i];
  1114.  
  1115.       line_data->red    = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  1116.       line_data->green  = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  1117.       line_data->blue   = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  1118.  
  1119.       if (psize > 3)
  1120.       {
  1121.         line_data->transm = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  1122.       }
  1123.       else
  1124.       {
  1125.         line_data->transm = (unsigned char *)NULL;
  1126.       }
  1127.     }
  1128.   }
  1129.  
  1130.   /* Read the image into the buffer */
  1131.  
  1132.   if (cflag)
  1133.   {
  1134.     /* RLE compressed images */
  1135.  
  1136.     if (cmlen > 0)
  1137.     {
  1138.       if (orien)
  1139.       {
  1140.         map_line = Image->data.map_lines[0];
  1141.       }
  1142.       else
  1143.       {
  1144.         map_line = Image->data.map_lines[height-1];
  1145.       }
  1146.     }
  1147.     else
  1148.     {
  1149.       if (orien)
  1150.       {
  1151.         line_data = &Image->data.rgb_lines[0];
  1152.       }
  1153.       else
  1154.       {
  1155.         line_data = &Image->data.rgb_lines[height-1];
  1156.       }
  1157.     }
  1158.  
  1159.     i = 0; /* row counter */
  1160.     j = 0; /* column counter */
  1161.  
  1162.     while (i < height)
  1163.     {
  1164.       /* Grab a header */
  1165.  
  1166.       if ((h = fgetc(filep)) == EOF)
  1167.       {
  1168.         Error("Error reading data from TGA image.\n");
  1169.       }
  1170.  
  1171.       if (h & 0x80)
  1172.       {
  1173.         /* Repeat buffer */
  1174.  
  1175.         h &= 0x7F;
  1176.  
  1177.         for (k = 0; k < psize; k++)
  1178.         {
  1179.           if ((temp = fgetc(filep)) == EOF)
  1180.           {
  1181.             Error("Error reading data from TGA image.\n");
  1182.           }
  1183.           else
  1184.           {
  1185.             bytes[k] = (unsigned char)temp;
  1186.           }
  1187.         }
  1188.  
  1189.         if (cmlen == 0)
  1190.         {
  1191.           convert_targa_color(&pixel, psize, bytes);
  1192.         }
  1193.  
  1194.         for (; h >= 0; h--)
  1195.         {
  1196.           if (cmlen > 0)
  1197.           {
  1198.             map_line[j] = bytes[0];
  1199.           }
  1200.           else
  1201.           {
  1202.             line_data->red[j]    = (unsigned char)pixel.Red;
  1203.             line_data->green[j]  = (unsigned char)pixel.Green;
  1204.             line_data->blue[j]   = (unsigned char)pixel.Blue;
  1205.             if (psize > 3)
  1206.             {
  1207.               line_data->transm[j] = (unsigned char)pixel.Transmit;
  1208.             }
  1209.           }
  1210.  
  1211.           if (++j == width)
  1212.           {
  1213.             i++;
  1214.  
  1215.             if (cmlen > 0)
  1216.             {
  1217.               if (orien)
  1218.               {
  1219.                 map_line = Image->data.map_lines[i];
  1220.               }
  1221.               else
  1222.               {
  1223.                 map_line = Image->data.map_lines[height-i-1];
  1224.               }
  1225.             }
  1226.             else
  1227.             {
  1228.               line_data += (orien ? 1 : -1);
  1229.             }
  1230.  
  1231.             j = 0;
  1232.           }
  1233.         }
  1234.       }
  1235.       else
  1236.       {
  1237.         /* Copy buffer */
  1238.  
  1239.         for (; h >= 0; h--)
  1240.         {
  1241.           for (k = 0; k < psize ; k++)
  1242.           {
  1243.             if ((temp = fgetc(filep)) == EOF)
  1244.             {
  1245.               Error("Error reading data from TGA image.\n");
  1246.             }
  1247.             else
  1248.             {
  1249.               bytes[k] = (unsigned char)temp;
  1250.             }
  1251.           }
  1252.  
  1253.           if (cmlen > 0)
  1254.           {
  1255.             map_line[j] = bytes[0];
  1256.           }
  1257.           else
  1258.           {
  1259.             convert_targa_color(&pixel, psize, bytes);
  1260.  
  1261.             line_data->red[j]    = (unsigned char)pixel.Red;
  1262.             line_data->green[j]  = (unsigned char)pixel.Green;
  1263.             line_data->blue[j]   = (unsigned char)pixel.Blue;
  1264.             if (psize > 3)
  1265.             {
  1266.               line_data->transm[j] = (unsigned char)pixel.Transmit;
  1267.             }
  1268.           }
  1269.  
  1270.           if (++j == width)
  1271.           {
  1272.             i++;
  1273.  
  1274.             if (cmlen > 0)
  1275.             {
  1276.               if (orien)
  1277.               {
  1278.                 map_line = Image->data.map_lines[i];
  1279.               }
  1280.               else
  1281.               {
  1282.                 map_line = Image->data.map_lines[height-i-1];
  1283.               }
  1284.             }
  1285.             else
  1286.             {
  1287.               line_data += (orien ? 1 : -1);
  1288.             }
  1289.  
  1290.             j = 0;
  1291.           }
  1292.         }
  1293.       }
  1294.     }
  1295.   }
  1296.   else
  1297.   {
  1298.     /* Simple raster image file, read in all of the pixels */
  1299.  
  1300.     if (cmlen == 0)
  1301.     {
  1302.       if (orien)
  1303.       {
  1304.         line_data = &Image->data.rgb_lines[0];
  1305.       }
  1306.       else
  1307.       {
  1308.         line_data = &Image->data.rgb_lines[height-1];
  1309.       }
  1310.     }
  1311.  
  1312.     for (i = 0; i < height; i++)
  1313.     {
  1314.       if (cmlen > 0)
  1315.       {
  1316.         if (orien)
  1317.         {
  1318.           map_line = Image->data.map_lines[i];
  1319.         }
  1320.         else
  1321.         {
  1322.           map_line = Image->data.map_lines[height-i-1];
  1323.         }
  1324.       }
  1325.  
  1326.       for (j = 0; j < width; j++)
  1327.       {
  1328.         for (k = 0; k < psize; k++)
  1329.         {
  1330.           if ((temp = fgetc(filep)) == EOF)
  1331.           {
  1332.             Error("Error reading data from TGA image.\n");
  1333.           }
  1334.           else
  1335.           {
  1336.             bytes[k] = (unsigned char)temp;
  1337.           }
  1338.         }
  1339.  
  1340.         if (cmlen > 0)
  1341.         {
  1342.           map_line[j] = bytes[0];
  1343.         }
  1344.         else
  1345.         {
  1346.           convert_targa_color(&pixel, psize, bytes);
  1347.  
  1348.           line_data->red[j]    = (unsigned char)pixel.Red;
  1349.           line_data->green[j]  = (unsigned char)pixel.Green;
  1350.           line_data->blue[j]   = (unsigned char)pixel.Blue;
  1351.           if (psize > 3)
  1352.           {
  1353.             line_data->transm[j] = (unsigned char)pixel.Transmit;
  1354.           }
  1355.         }
  1356.       }
  1357.  
  1358.       if (cmlen == 0)
  1359.       {
  1360.         line_data += (orien ? 1 : -1);
  1361.       }
  1362.     }
  1363.   }
  1364.  
  1365.   /* Any data following the image is ignored. */
  1366.  
  1367.   /* Close the image file */
  1368.  
  1369.   fclose(filep);
  1370. }
  1371.